home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
os2
/
e33el2.zip
/
emacs
/
19.33
/
lisp
/
gomoku.el
< prev
next >
Wrap
Lisp/Scheme
|
1996-05-23
|
45KB
|
1,183 lines
;;; gomoku.el --- Gomoku game between you and Emacs
;; Copyright (C) 1988, 1994, 1996 Free Software Foundation, Inc.
;; Author: Philippe Schnoebelen <phs@lifia.imag.fr>
;; Adapted-By: ESR, Daniel.Pfeiffer@Informatik.START.dbp.de
;; Keywords: games
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; RULES:
;;
;; Gomoku is a game played between two players on a rectangular board. Each
;; player, in turn, marks a free square of its choice. The winner is the first
;; one to mark five contiguous squares in any direction (horizontally,
;; vertically or diagonally).
;;
;; I have been told that, in "The TRUE Gomoku", some restrictions are made
;; about the squares where one may play, or else there is a known forced win
;; for the first player. This program has no such restriction, but it does not
;; know about the forced win, nor do I. Furthermore, you probably do not know
;; it yourself :-).
;; There are two main places where you may want to customize the program: key
;; bindings and board display. These features are commented in the code. Go
;; and see.
;; HOW TO USE:
;;
;; The command "M-x gomoku" displays a
;; board, the size of which depends on the size of the current window. The
;; size of the board is easily modified by giving numeric arguments to the
;; gomoku command and/or by customizing the displaying parameters.
;;
;; Emacs plays when it is its turn. When it is your turn, just put the cursor
;; on the square where you want to play and hit RET, or X, or whatever key you
;; bind to the command gomoku-human-plays. When it is your turn, Emacs is
;; idle: you may switch buffers, read your mail, ... Just come back to the
;; *Gomoku* buffer and resume play.
;; ALGORITHM:
;;
;; The algorithm is briefly described in section "THE SCORE TABLE". Some
;; parameters may be modified if you want to change the style exhibited by the
;; program.
;;; Code:
;;;
;;; GOMOKU MODE AND KEYMAP.
;;;
(defvar gomoku-mode-hook nil
"If non-nil, its value is called on entry to Gomoku mode.")
(defvar gomoku-mode-map nil
"Local keymap to use in Gomoku mode.")
(if gomoku-mode-map nil
(setq gomoku-mode-map (make-sparse-keymap))
;; Key bindings for cursor motion.
(define-key gomoku-mode-map "y" 'gomoku-move-nw) ; y
(define-key gomoku-mode-map "u" 'gomoku-move-ne) ; u
(define-key gomoku-mode-map "b" 'gomoku-move-sw) ; b
(define-key gomoku-mode-map "n" 'gomoku-move-se) ; n
(define-key gomoku-mode-map "h" 'backward-char) ; h
(define-key gomoku-mode-map "l" 'forward-char) ; l
(define-key gomoku-mode-map "j" 'gomoku-move-down) ; j
(define-key gomoku-mode-map "k" 'gomoku-move-up) ; k
(define-key gomoku-mode-map [kp-7] 'gomoku-move-nw)
(define-key gomoku-mode-map [kp-9] 'gomoku-move-ne)
(define-key gomoku-mode-map [kp-1] 'gomoku-move-sw)
(define-key gomoku-mode-map [kp-3] 'gomoku-move-se)
(define-key gomoku-mode-map [kp-4] 'backward-char)
(define-key gomoku-mode-map [kp-6] 'forward-char)
(define-key gomoku-mode-map [kp-2] 'gomoku-move-down)
(define-key gomoku-mode-map [kp-8] 'gomoku-move-up)
(define-key gomoku-mode-map "\C-n" 'gomoku-move-down) ; C-n
(define-key gomoku-mode-map "\C-p" 'gomoku-move-up) ; C-p
;; Key bindings for entering Human moves.
(define-key gomoku-mode-map "X" 'gomoku-human-plays) ; X
(define-key gomoku-mode-map "x" 'gomoku-human-plays) ; x
(define-key gomoku-mode-map " " 'gomoku-human-plays) ; SPC
(define-key gomoku-mode-map "\C-m" 'gomoku-human-plays) ; RET
(define-key gomoku-mode-map "\C-c\C-p" 'gomoku-human-plays) ; C-c C-p
(define-key gomoku-mode-map "\C-c\C-b" 'gomoku-human-takes-back) ; C-c C-b
(define-key gomoku-mode-map "\C-c\C-r" 'gomoku-human-resigns) ; C-c C-r
(define-key gomoku-mode-map "\C-c\C-e" 'gomoku-emacs-plays) ; C-c C-e
(define-key gomoku-mode-map [kp-enter] 'gomoku-human-plays)
(define-key gomoku-mode-map [insert] 'gomoku-human-plays)
(define-key gomoku-mode-map [down-mouse-1] 'gomoku-click)
(define-key gomoku-mode-map [drag-mouse-1] 'gomoku-click)
(define-key gomoku-mode-map [mouse-1] 'gomoku-click)
(define-key gomoku-mode-map [down-mouse-2] 'gomoku-click)
(define-key gomoku-mode-map [mouse-2] 'gomoku-mouse-play)
(define-key gomoku-mode-map [drag-mouse-2] 'gomoku-mouse-play)
(substitute-key-definition 'previous-line 'gomoku-move-up
gomoku-mode-map (current-global-map))
(substitute-key-definition 'next-line 'gomoku-move-down
gomoku-mode-map (current-global-map))
(substitute-key-definition 'beginning-of-line 'gomoku-beginning-of-line
gomoku-mode-map (current-global-map))
(substitute-key-definition 'end-of-line 'gomoku-end-of-line
gomoku-mode-map (current-global-map))
(substitute-key-definition 'undo 'gomoku-human-takes-back
gomoku-mode-map (current-global-map))
(substitute-key-definition 'advertised-undo 'gomoku-human-takes-back
gomoku-mode-map (current-global-map)))
(defvar gomoku-emacs-won ()
"*For making font-lock use the winner's face for the line.")
(defvar gomoku-font-lock-O-face
(if window-system
(list (facemenu-get-face 'fg:red) 'bold))
"*Face to use for Emacs' O.")
(defvar gomoku-font-lock-X-face
(if window-system
(list (facemenu-get-face 'fg:green) 'bold))
"*Face to use for your X.")
(defvar gomoku-font-lock-keywords
'(("O" . gomoku-font-lock-O-face)
("X" . gomoku-font-lock-X-face)
("[-|/\\]" 0 (if gomoku-emacs-won
gomoku-font-lock-O-face
gomoku-font-lock-X-face)))
"*Font lock rules for Gomoku.")
(put 'gomoku-mode 'front-sticky
(put 'gomoku-mode 'rear-nonsticky '(intangible)))
(put 'gomoku-mode 'intangible 1)
(defun gomoku-mode ()
"Major mode for playing Gomoku against Emacs.
You and Emacs play in turn by marking a free square. You mark it with X
and Emacs marks it with O. The winner is the first to get five contiguous
marks horizontally, vertically or in diagonal.
You play by moving the cursor over the square you choose and hitting \\[gomoku-human-plays].
Other useful commands:
\\{gomoku-mode-map}
Entry to this mode calls the value of `gomoku-mode-hook' if that value
is non-nil. One interesting value is `turn-on-font-lock'."
(interactive)
(setq major-mode 'gomoku-mode
mode-name "Gomoku")
(gomoku-display-statistics)
(use-local-map gomoku-mode-map)
(make-local-variable 'font-lock-defaults)
(setq font-lock-defaults '(gomoku-font-lock-keywords t))
(toggle-read-only t)
(run-hooks 'gomoku-mode-hook))
;;;
;;; THE BOARD.
;;;
;; The board is a rectangular grid. We code empty squares with 0, X's with 1
;; and O's with 6. The rectangle is recorded in a one dimensional vector
;; containing padding squares (coded with -1). These squares allow us to
;; detect when we are trying to move out of the board. We denote a square by
;; its (X,Y) coords, or by the INDEX corresponding to them in the vector. The
;; leftmost topmost square has coords (1,1) and index gomoku-board-width + 2.
;; Similarly, vectors between squares may be given by two DX, DY coords or by
;; one DEPL (the difference between indexes).
(defvar gomoku-board-width nil
"Number of columns on the Gomoku board.")
(defvar gomoku-board-height nil
"Number of lines on the Gomoku board.")
(defvar gomoku-board nil
"Vector rec